#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""Australia data format (Kingston, Mawson)

Copyright (c) 2011-2014 Christian T. Steigies <steigies@physik.uni-kiel.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

This module offers functions to read NM data in ASCII format as used in Australia
and return data in the format as used by NMDB."""

__author__ = "Christian T. Steigies <steigies@physik.uni-kiel.de>"
__license__ = "GPL License"

import os
import sys
from datetime import datetime, timedelta
import gzip
import urllib2

from nmdb.station.station_data import check_data, check_pressure
#from nmdb.tools.configtool import parse_config
from nmdb.tools.datetool import doy2date, year2, valid_date
from nmdb.tools.pressure import mbar

australia_shortnames = {"kgsn": "kin", "mwsn": "maw"}
australia_station = ["kgsn", "mwsn"] # KIN, MAW
australia_longnames = {"kgsn": "Kingston",
                       "mwsn": "Mawson"}

## --------------------------------------------------------------------------
def read_rt(options, station, data_type, year, month, day):
    """read realtime data

    options     verbose, dryrun, ...
    station     station short name, must be valid station
    data_type   "1m", "1h", "env", "meta"
    year        integer (1950-9999)
    month       integer (1-12)
    day         integer (1-31)
    
    return list of values in nmdb format
    """

    if station in australia_station:
        pass
    else:
        raise ValueError  # wrong station

    if valid_date(year, month, day):
        if data_type in ["1h"]:
            value = read_sse(options, station, data_type, year, month, day)
        elif data_type in ["1m"]:
            value = read_sse(options, station, data_type, year, month, day)
        elif data_type in ["env", "meta"]:
            value = []
        elif data_type in ["ori"]:
            print "use 1m instead of ori"
            raise ValueError  # illegal data_type
        else:
            raise ValueError  # illegal data_type
    else:
        value = None

    return value

## --------------------------------------------------------------------------
def read_rev(options, station, data_type, year, month, day):
    """read revised data

    options     verbose, dryrun, ...
    station     station short name, must be valid station
    data_type   "1m", "1h", "env", "meta"
    year        integer (1950-9999), may not be None
    month       integer (1-12), if None, read month 1-12
    day         integer (1-31), if None, read day 1-31

    return list of values in nmdb format
    """

    if station in australia_station:
        pass
    else:
        raise ValueError  # wrong station

    if valid_date(year, month, day):
        if data_type in ["1h"]:
            value = read_cdt(options, station, data_type, year, month, day)
        elif data_type in ["1m"]:
            value = read_cdt(options, station, data_type, year, month, day)
        elif data_type in ["env", "meta"]:
            value = []
        else:
            raise ValueError  # illegal data_type
    else:
        value = None

    return value

## --------------------------------------------------------------------------
def read_cdt(options, station, data_type, year=None, month=None, day=None):
    """
    corrected data:
        ftp.ips.gov.au:/wdc-data/cosray/data/KIN/CDT/2001-2013
        ftp.ips.gov.au:/wdc-data/cosray/data/MAW/CDT/2002-2013
    filename:
        MAW_02_12_31.CDT
        MAW_13_10_22.CDT
    data format:
        date and time in UTC of the END of the measurement (not the START!)
        Corrected counts for the whole monitor for the measurement interval)
        Atmospheric pressure in mbar
        Uncorrected counts for the whole monitor for the measurement interval)
    """

    if data_type in ["1h", "env", "meta"]:
        raise ValueError  # data not yet available

    if station in australia_station:
        sname = australia_shortnames[station].upper()
    else:
        sname = station.upper()
        #raise ValueError  TODO?
        
    data = []

    useftp = False
    #useftp = True
    #header = ["Date", "Time", "Corr", "Pres", "Uncorr"]
    if useftp:  # read directly from FTP server
        ftpserver="ftp://ftp.ips.gov.au/wdc-data/cosray/data/"
    else:  # read from local copy
        ftpserver="/home/wdc_cosray/data"
    filename = "%s/%s/CDT/%04i/%s_%02i_%02i_%02i.CDT" % (ftpserver, sname, year, sname, year2(year), month, day)
    print "reading", filename

    try:
        if useftp:
            myfile = urllib2.urlopen(filename)
        else:
            myfile = open(filename, "r")
        line = myfile.readline()
        
        if data_type in ["1m", "ori", "rev"]:
            interval = 60  # calculate actual interval?
        elif data_type in["1h"]:
            interval = 3600  # hour data
        else:
            print "unknown data:", data_type
            sys.exit(1)

        while line:
            line = myfile.readline()
            if len(line) < 40:
                break  # continue to skip line?

            (date, time, corr, press, uncorr) = line.split()
            (year, month, day) = date.split("/")
            (hour, minute, second) = time.split(":")
            year = int(year)
            month = int(month)
            day = int(day)
            hour = int(hour)
            minute = int(minute)
            second = int(second)
            
            if second > 0:
                if second >= 10:
                    print "warning: invalid timestamp", date, time, "\t skipping data"
                    continue  # invalid data
                else:
                    print "warning: invalid timestamp", date, time, "\t setting seconds to 0"
                    pass # set seconds to 0
            timestamp = datetime(year, month, day, hour, minute, 0)  # seconds must be == 0
            # convert from end to start of measurement
            timestamp -= timedelta(seconds=interval)
            
            # convert to counts per second
            corr = round(float(corr)/interval, 3)
            press = round(float(press), 2)
            uncorr = round(float(uncorr)/interval, 3)
            
            uncorr = check_data(uncorr, cr_min=10., cr_max=10000.)
            press = check_pressure(press, p_min=900., p_max=1070.)
            corr = check_data(corr, cr_min=10., cr_max=10000.)
            ceff = corr

            # order as in NMDB
            data.append([timestamp, interval, uncorr, ceff, corr, press])

        return data

    except IOError:
        print "file %s not found" % (filename)
    except urllib2.URLError:
        print "file %s not found", filename


## --------------------------------------------------------------------------
def read_sse(options, station, data_type, year=None, month=None, day=None):
    """
    quicklook / real-time data:
        ftp.ips.gov.au:/wdc-data/cosray/data/KIN/2004-2015
        ftp.ips.gov.au:/wdc-data/cosray/data/MAW/2004-2015
        /data/kermes/NMDB/aus/MAW/2014/MAW20140101.SSE
    filename:
        
    data format:
        year, doy, hour, minute in UTC of the START of the measurement?
        Corrected counts for the whole monitor for the measurement interval)?
        Uncorrected counts for the whole monitor for the measurement interval)?
        Atmospheric pressure in torr?
    """

    if data_type in ["1h", "env", "meta"]:
        raise ValueError  # data not yet available

    if station in australia_station:
        sname = australia_shortnames[station].upper()
    else:
        sname = station.upper()
        #raise ValueError  TODO?

    data = []
    #header = ["Date", "Time", "Corr", "Pres", "Uncorr"]
    #ftpserver="ftp://ftp.ips.gov.au/wdc-data/cosray/data/"
    #gzip.GzipFile(fileobj=handle)
    ftpserver="/home/wdc_cosray/data"
    filename = "%s/%s/%04i/%s%04i%02i%02i.SSE" % (ftpserver, sname, year, sname, year, month, day)
    print "reading", filename

    data = []
    if data_type in ["1m", "ori", "rev"]:
        interval = 60  # calculate actual interval?
    elif data_type in["1h"]:
        interval = 3600  # hour data
    else:
        print "unknown data:", data_type
        sys.exit(1)

    try:
        #myfile = open(filename, "r")
        myfile = gzip.open(filename+".gz", 'rb')
        line = True
        while line:
            line = myfile.readline()
            if len(line) < 36:
                break
            (year, doy, hour, minute, corr, uncorr, press) = line.split()
            date = doy2date(int(year), int(doy))
            timestamp = datetime(date.year, date.month, date.day, int(hour), int(minute))
            corr = float(corr)
            uncorr = float(uncorr)
            press = mbar(float(press))
            #print timestamp, corr, uncorr, press, type(press)
            
            # convert to counts per second
            corr = round(corr/interval, 3)
            press = round(press, 2)
            uncorr = round(uncorr/interval, 3)
            
            uncorr = check_data(uncorr, cr_min=10., cr_max=10000.)
            press = check_pressure(press, p_min=900., p_max=1070.)
            corr = check_data(corr, cr_min=10., cr_max=10000.)
            ceff = corr

            # order as in NMDB
            data.append([timestamp, interval, uncorr, ceff, corr, press])

    except IOError:
        print "file %s not found" % (filename)
        #sys.exit(1)

    return data

## --------------------------------------------------------------------------
def main():
    import optparse
    parser = optparse.OptionParser("usage: %prog [options]")
    parser.add_option("-v", dest="verbose", default=0, action="count",
            help="increment output verbosity; may be specified multiple times")
    (options, args) = parser.parse_args()

    print "This is the australia module."

    station = "kgsn"
    station = "mwsn"
    data_type="1h"
    data_type="1m"
    year = 2013
    month = 10
    day = 1

    #data = read_rev(options, station, data_type, year, month, day)
    data = read_rt(options, station, data_type, year, month, day)
    for line in data:
        print line

## --------------------------------------------------------------------------
if __name__ == '__main__':
    main()
